/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.anhndt.audiobook.ui;

import com.anhndt.audiobook.business.ListLoaderTask;
import com.anhndt.audiobook.ui.renderer.ItemRenderer;
import com.anhndt.audiobook.business.Resource;
import com.anhndt.audiobook.entity.ItemEntity;
import com.anhndt.audiobook.iface.ProcessListener;
import com.anhndt.audiobook.parser.ItemParser;
import com.anhndt.audiobook.ui.renderer.ItemTickerRenderer;
import com.anhndt.audiobook.utils.DBUtil;
import com.anhndt.audiobook.utils.DialogUtil;
import com.anhndt.audiobook.utils.StringUtil;
import com.anhndt.audiobook.utils.Util;
import com.sun.lwuit.Button;
import com.sun.lwuit.Command;
import com.sun.lwuit.Component;
import com.sun.lwuit.Container;
import com.sun.lwuit.Display;
import com.sun.lwuit.Form;
import com.sun.lwuit.Graphics;
import com.sun.lwuit.Image;
import com.sun.lwuit.Label;
import com.sun.lwuit.List;
import com.sun.lwuit.TextField;
import com.sun.lwuit.events.ActionEvent;
import com.sun.lwuit.events.ActionListener;
import com.sun.lwuit.events.FocusListener;
import com.sun.lwuit.layouts.BorderLayout;
import com.sun.lwuit.list.DefaultListModel;
import com.sun.lwuit.list.ListCellRenderer;
import java.util.Hashtable;
import java.util.Vector;
//#if BB || BB_TrackWheel
//# import net.rim.device.api.ui.Keypad;
//# import com.sun.lwuit.Display;
//#endif

/**
 *
 * @author Sun
 */
public abstract class BaseForm implements ActionListener {

//    public static final byte TAG_CATEGORY = 0;
//    public static final byte TAG_ARTICLE = 1;
//    public static final byte TAG_ARTICLE_PART = 2;
    public static final byte TAG_FAVORITE = 3;
    public static final byte TAG_SEARCH = 4;
//    public static final byte TAG_DETAIL = 5;
    public static final byte TAG_UNKNOWN = 10;
    protected BaseForm formChild;
    protected BaseForm previous;
    protected ListItem listItem;
    protected Form form;
    protected ItemEntity parentEntity;
    protected TextField textSearch;
    protected Container panelSearch;
    protected Label messageIcon;
    protected Command cmdBack, cmdView, cmdMainScreen, cmdSearch;
    protected Container body;
    protected String title;
    protected byte tag = TAG_UNKNOWN;
    protected static boolean hasMessage;
    private static boolean modeSearch;
    private boolean hasSupportSearch;
    public static String keySearch;
    ListLoaderTask loader;
//    private static  BaseForm currentForm;
//
//    public static BaseForm getCurrentForm() {
//        return currentForm;
//    }

    public boolean isModeSearch() {
        return modeSearch;
    }

    public boolean isHasSupportSearch() {
        return hasSupportSearch;
    }

    public void setSupportSearch(boolean hasSupportSearch) {
        this.hasSupportSearch = hasSupportSearch;
    }

    public void setModeSearch(boolean mode) {
        setModeSearch(mode, false);
    }

    public void setModeSearch(boolean mode, boolean init) {
        if (!hasSupportSearch) {
            return;
        }
        try {
            Thread.sleep(10);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
        System.out.println("******** " + getClass() + "   SET MODE SEARCH " + mode);
        if (tag != TAG_SEARCH) {
            modeSearch = mode;
        } else {
            mode = true;
        }
        if (cmdSearch != null) {
            cmdSearch.setCommandName(mode ? Resource.CMD_INVISIBLE_SEARCH : Resource.CMD_VISIBLE_SEARCH);
        }

        if (mode && panelSearch == null) {
            textSearch = new TextSearch();
            textSearch.setInputMode("abc");
            textSearch.setText(keySearch == null ? "" : keySearch.trim());
            textSearch.setHint("search in here");
            textSearch.setMaxSize(50);
//            textSearch.setIsScrollVisible(false);
//            textSearch.setSingleLineTextArea(true);

            panelSearch = new Container(new BorderLayout());
            panelSearch.setUIID("SearchPane");
            panelSearch.addComponent(BorderLayout.CENTER, textSearch);
            if (Display.getInstance().isTouchScreenDevice()) {
                Button btnSearch = new Button(Util.getImage("search_text"));
                btnSearch.setUIID("ButtonSearch");
                btnSearch.setFocusable(false);
                btnSearch.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent evt) {
                        search();
                    }
                });
                panelSearch.addComponent(BorderLayout.WEST, btnSearch);
            }
        }
        if (form != null && panelSearch != null) {
            try {
                if (mode) {
                    form.setTitle("");
//                    form.getContainer().removeComponent(form.getTitleArea());
                    form.getContainer().addComponent(BorderLayout.NORTH, panelSearch);
                    if(!init)
                        textSearch.requestFocus();
                } else {
                    form.getContainer().removeComponent(panelSearch);
//                    form.getContainer().addComponent(BorderLayout.NORTH, form.getTitleArea());
                    form.setTitle(title);
                    textSearch = null;
                    panelSearch = null;
                    if (listItem != null) {
                        listItem.requestFocus();
                    }
                }
                form.layoutContainer();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public BaseForm(String title, BaseForm previous, ItemEntity parentEntity) {
        this(TAG_UNKNOWN, title, previous, parentEntity);
    }

    public BaseForm(byte tag, String title, BaseForm previous, ItemEntity parentEntity) {
        this.tag = tag;
        this.title = title;
        this.previous = previous;
        this.parentEntity = parentEntity;
    }

    boolean checkChar(int keyCode, char c) {
        return keyCode == Character.toUpperCase(c) || keyCode == Character.toLowerCase(c);
    }

    int getKeyCode(int keyCode) {
        int keyCodeTmp = keyCode;
        if (form != null && form.getFocused() != null && form.getFocused() instanceof TextField) {
            return keyCodeTmp;
        }
        //#if BB || BB_TrackWheel
//#         if (Keypad.getHardwareLayout() == Keypad.HW_LAYOUT_32) {
//#             if (checkChar(keyCode, 'd')) {
//# //                DialogUtil.showInfoDialog("[FIRE] keyCode = " + keyCode);
//#                 keyCodeTmp = Display.getInstance().getKeyCode(Display.GAME_FIRE);
//#             } else if (checkChar(keyCode, 'f')) {
//# //                DialogUtil.showInfoDialog("[RIGHT] keyCode = " + keyCode);
//#                 keyCodeTmp = Display.getInstance().getKeyCode(Display.GAME_RIGHT);
//#             } else if (checkChar(keyCode, 's')) {
//# //                DialogUtil.showInfoDialog("[LEFT] keyCode = " + keyCode);
//#                 keyCodeTmp = Display.getInstance().getKeyCode(Display.GAME_LEFT);
//#             } else if (checkChar(keyCode, 'e')) {
//# //                DialogUtil.showInfoDialog("[UP] keyCode = " + keyCode);
//#                 keyCodeTmp = Display.getInstance().getKeyCode(Display.GAME_UP);
//#             } else if (checkChar(keyCode, 'x')) {
//# //                DialogUtil.showInfoDialog("[DOWN] keyCode = " + keyCode);
//#                 keyCodeTmp = Display.getInstance().getKeyCode(Display.GAME_DOWN);
//#             }
//#         }
//# 
        //#endif
        return keyCodeTmp;
    }

    protected ListCellRenderer getRenderer() {
        return new ItemTickerRenderer(ItemRenderer.TYPE_TWO);
    }

    protected void addMessageIcon() {
        if (hasMessage && form != null && getClass() != MediaPlayerForm.class) {
            messageIcon = new Label(Util.getImage("message"));
            messageIcon.getUnselectedStyle().setBgImage(form.getTitleComponent().getUnselectedStyle().getBgImage());
            form.addComponentTitle(messageIcon, BorderLayout.EAST);
            form.getTitleArea().repaint();
        }
    }

    protected void removeMessageIcon() {
        hasMessage = false;
        if (form != null && messageIcon != null) {
            form.getTitleArea().removeComponent(messageIcon);
            messageIcon.setIcon(null);
            messageIcon = null;
        }
    }

    protected void init() {
        //revemo formchild out memory
        if (formChild != null) {
            formChild = null;
        }
        body = new Container(new BorderLayout());
        body.setUIID("Body");
        body.setScrollableY(true);
        body.setScrollableX(false);
        form = new Form(title) {

            public void keyPressed(int keyCode) {
                keyCode = getKeyCode(keyCode);
                if (BaseForm.this.keyPressed(keyCode)) {
                    super.keyPressed(keyCode);
                }
            }

            public void keyReleased(int keyCode) {
                keyCode = getKeyCode(keyCode);
                super.keyReleased(keyCode);
            }

            protected void onShowCompleted() {
                BaseForm.this.onShowCompleted();
            }
        };
        form.setScrollableX(false);
        form.setScrollableY(false);
        form.setLayout(new BorderLayout());
        form.addComponent(BorderLayout.CENTER, body);
        if (hasSupportSearch) {
            setModeSearch(modeSearch,true);
        }
        cmdBack = new Command((getClass() == MainForm.class) ? Resource.CMD_EXIT : Resource.CMD_BACK) {

            public void actionPerformed(ActionEvent evt) {
                backScreen();
            }
        };
        cmdMainScreen = new Command(Resource.CMD_MAIN_SCREEN) {

            public void actionPerformed(ActionEvent evt) {
                onShowMainForm();
                MainForm.showMainScreen();
            }
        };
        cmdView = new Command(Resource.CMD_VIEW);
        form.addCommand(cmdBack);
        form.setBackCommand(cmdBack);
        addCommand();
        addMessageIcon();
    }

    protected void addCommand() {
        if (getClass() != MainForm.class) {
            form.addCommand(cmdMainScreen);
        }
        form.addCommandListener(this);

        if (getClass() != MediaPlayerForm.class && Util.lastArticleEntity != null && Util.lastArticleEntity.typeEntity == ItemEntity.TYPE_ARTICLE) {
            form.addCommand(new Command(Resource.CMD_RESUME) {

                public void actionPerformed(ActionEvent evt) {
                    new MediaPlayerForm(null, BaseForm.this, Util.lastArticleEntity, Util.lastIndexArticlePartID).show();
                }
            });
        }

        if (hasSupportSearch && tag != TAG_SEARCH) {
            cmdSearch = new Command(modeSearch ? Resource.CMD_INVISIBLE_SEARCH : Resource.CMD_VISIBLE_SEARCH) {

                public void actionPerformed(ActionEvent evt) {
                    BaseForm.this.setModeSearch(!modeSearch);
                }
            };
            form.addCommand(cmdSearch);
        }
    }

    protected void onShowMainForm() {
        final ItemEntity item = (listItem != null && listItem.size() > 0) ? (ItemEntity) listItem.getSelectedItem() : parentEntity;
        if (item != null && tag == TAG_SEARCH) {
            item.removeAllChilrends();
        }
    }

    protected boolean createListItem(Vector items, ListCellRenderer defaultRenderer) {
        if (items == null || items.size() == 0) {
            return false;
        }
        if (listItem == null) {
            listItem = new ListItem(items);
            listItem.setListCellRenderer(defaultRenderer);
            listItem.setItemGap(-1);
            listItem.setBorderGap(0);
            listItem.addActionListener(this);
            body.addComponent(BorderLayout.CENTER, listItem);
        } else {
            listItem.setModel(new DefaultListModel(items));
        }
        return true;
    }

    public String getPrefixLoadThumb() {
        String prefix = "";
        if (getClass() == CategoryForm.class) {
            prefix = "c";
        } else if (getClass() == ArticleForm.class) {
            prefix = "a";
        } else if (getClass() == MediaPlayerForm.class) {
            prefix = "t";
        } else if (getClass() == MainForm.class) {
            prefix = "m";
        }
        return prefix;
    }

    void stopLoadThumb() {
        if (loader != null && loader.isLoading()) {
            loader.stop();
        }
        loader = null;
    }

    protected void loadThumb(Vector entities) {
        loadThumb(entities, true);
    }

    protected void loadThumb(Vector entities, boolean crop) {
        loadThumb(entities, Util.sizeThumb, Util.sizeThumb, getPrefixLoadThumb(), crop);
    }

    protected void loadThumb(Vector entities, int h, int w) {
        loadThumb(entities, h, w, getPrefixLoadThumb(), true);
    }

    protected void loadThumb(final Vector entities, int h, int w, final String prefix, boolean crop) {
        loadThumb(entities, h, w, prefix, crop, null);
    }

    protected void loadThumb(final Vector entities, int h, int w, int quality, final String prefix, boolean crop, final ProcessListener callbackLoadedImage) {
        if (entities == null || entities.size() == 0) {
            return;
        }
        int size = entities.size();
        String[] urls = new String[size];
        final Hashtable entitiesReallyLoadImage = new Hashtable();
        ItemEntity entity = null;
        for (int i = 0; i < size; i++) {
            entity = (ItemEntity) entities.elementAt(i);
            String idRMS = prefix + entity.id;
            //neu da load image va save lai trong RMS roi
            try {
                if (Util.isItemLoadedThumb(idRMS)) {
                    byte[] data = DBUtil.loadData(DBUtil.DB_IMAGE, idRMS);
                    Image icon = (data != null) ? Image.createImage(data, 0, data.length) : null;
                    entity.icon = icon;
                    if (callbackLoadedImage != null) {
                        callbackLoadedImage.onSuccess(icon, 0);
                    }
                    form.repaint();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //neu da load icon roi thi bo di, ko load lai nua
            if (entity.icon != null) {
                continue;
            }
            String c = (crop) ? "1" : "0";
            urls[i] = StringUtil.format(Util.RESIZE_URL_WITH_QUALITY,
                    new String[]{c, "" + w, "" + h, quality + "", entity.getThumbUrl()});
            entitiesReallyLoadImage.put("" + i, entity);
        }
        if (entitiesReallyLoadImage.isEmpty()) {
            return;
        }
        ProcessListener listener = new ProcessListener() {

            public void onSuccess(Object result, int index) {
                try {
                    byte[] data = (byte[]) result;
                    ItemEntity entity = (ItemEntity) entitiesReallyLoadImage.get("" + index);
                    //load image into thumb
                    Image icon = Image.createImage(data, 0, data.length);
                    entity.icon = icon;
                    //save image into RMS
                    String idRMS = prefix + entity.id;
                    Util.addIdItemLoadedThumb(idRMS);
                    DBUtil.saveData(DBUtil.DB_IMAGE, idRMS, data);
                    if (callbackLoadedImage != null) {
                        callbackLoadedImage.onSuccess(icon, 0);
                    }
                    form.repaint();
                } catch (Exception e) {
                }
            }

            public void onError(String status, int index) {
            }
        };
        loader = new ListLoaderTask(urls, listener);
        loader.start();
    }

    protected void loadThumb(final Vector entities, int h, int w, final String prefix, boolean crop, final ProcessListener callbackLoadedImage){
        loadThumb(entities, h, w, 80, prefix, crop, callbackLoadedImage);
    }

    private void search() {
        String keyWord = textSearch.getText();
        if (keyWord.length() == 0) {
            return;
        }
        keySearch = keyWord;
        final ItemEntity item = (listItem != null && listItem.size() > 0) ? (ItemEntity) listItem.getSelectedItem() : parentEntity;
        //create callback
        ProcessListener callback = new ProcessListener() {

            public void onSuccess(Object result, int index) {
                Vector vtCounterItem = (Vector) item.getItemChildrends("" + ItemEntity.TYPE_COUNTER_ITEM);
//                Vector vtAdvText = (Vector) item.getItemChildrends("" + ItemEntity.TYPE_ADVERTISE_TEXT);
//                String advText = vtAdvText.size() > 0 ? vtAdvText.elementAt(0).toString() : null;

                ItemEntity counterItem = (vtCounterItem.size() > 0) ? (ItemEntity) vtCounterItem.elementAt(0) : null;
                item.counterChild = counterItem.counterChild;

                formChild = new ArticleForm(TAG_SEARCH, item.name, BaseForm.this, item);
                formChild.setModeSearch(true);
                showFormChild(formChild);
            }

            public void onError(String status, int index) {
            }
        };
        getResponseItemSearch(keySearch, item, callback);
    }

    protected void getResponseItemSearch(String keyWord, ItemEntity entity, ProcessListener callback) {
        ItemParser p = new ItemParser(keyWord, "" + Util.displayCounter, "" + 1);
        p.checkLoaded = false;
        String mainKey = "" + ItemEntity.TYPE_ARTICLE;
        String messageConfirm = Resource.TXT_WARRING_NO_RESULT;
        getResponseItem(entity, p, callback, mainKey, messageConfirm, true);
    }

    protected void getResponseItem(ItemEntity entity, ItemParser parser, ProcessListener callback) {
        getResponseItem(entity, parser, callback, true);

    }

    protected void getResponseItem(ItemEntity entity, ItemParser parser, ProcessListener callback, boolean isShowIndicator) {
        getResponseItem(entity, parser, callback, Resource.TXT_WARRING_UPDATETING, isShowIndicator);
    }

    protected void getResponseItem(ItemEntity entity, ItemParser parser, ProcessListener callback, String messageConfirm, boolean isShowIndicator) {
        getResponseItem(entity, parser, callback, entity.getMainKey(), messageConfirm, isShowIndicator);
    }

    /**
     *
     * @param entity
     * @param parser
     * @param callback
     * @param mainKey : Neu nhu khong co du lieu nao ung voi key la keyMain thi se show ra dialog message confirm
     * @param messageConfirm : Message se hien len
     * @param isShowIndicator
     */
    protected void getResponseItem(final ItemEntity entity, final ItemParser parser,
            final ProcessListener callback, String mainKey, final String messageConfirm, final boolean isShowIndicator) {
        final boolean showDialogError = parser.showError;
        if (tag == TAG_SEARCH) {
            mainKey = "" + ItemEntity.TYPE_ARTICLE;
        }
        final String realMainKey = mainKey;
        if (parser.checkLoaded && entity.loaded) {
            if (!StringUtil.isNullOrEmpty(mainKey) && entity.size(mainKey) <= 0) {
                if (showDialogError) {
                    DialogUtil.showInfoDialog(messageConfirm, true);
                }
            } else if (callback != null) {
                callback.onSuccess(entity, 0);
            }
            return;
        }
        Thread t = new Thread() {

            public void run() {
                try {
                    if (!parser.checkLoaded || !entity.loaded) {
                        parser.getResponse(entity);
                        //if finished and not exception
                        //setloaded for entity is true
                        if (parser.checkLoaded) {
                            entity.loaded = true;
                        }
                    }
                    parser.release();

                    if (!StringUtil.isNullOrEmpty(realMainKey) && entity.size(realMainKey) <= 0) {
                        if (showDialogError) {
                            DialogUtil.showInfoDialog(messageConfirm, true);
                        }
                    } else if (callback != null) {
                        callback.onSuccess(entity, 0);
                    }

                } catch (Exception ex) {
                    if (showDialogError) {
                        DialogUtil.showErrorConnectServer();
//                        DialogUtil.showDialog("[BaseForm" + ex.getMessage(), 1, new String[]{"OK"});
                    }
                    ex.printStackTrace();
                } finally {
                    if (form != null && isShowIndicator) {
                        Indicator.hide();
                    }
                }
            }
        };
        t.setPriority(Thread.MAX_PRIORITY);
        if (isShowIndicator) {
            Indicator.show(t);
        } else {
            t.start();
        }
    }

    public void show() {
//        Display.getInstance().setThirdSoftButton(false);
        if (formChild != null) {
            formChild.releaseAll();
            System.out.println("[SHOW] " + formChild.getClass() + "    ------------>  " + getClass().toString());
        }
        formChild = null;
        if (form == null) {
            init();
        }
        form.show();
        Util.gc();
    }

    public void showFormChild(BaseForm formChild) {
        if (formChild == null) {
            return;
        }
        releaseAll();
        formChild.show();
    }

    /**
     * ham nay se replace tat ca cac item trong list
     * bang 1 loat cac item duoc tao ra trong Vector categories
     * @param categories,selectedIndex
     */
    protected void changeListModel(Vector items, int selectedIndex) {
        createListItem(items, getRenderer());
        setSelectedIndex(selectedIndex);
    }

    protected void setSelectedIndex(int selectedIndex) {
        if (listItem == null || selectedIndex >= listItem.size() || selectedIndex < 0) {
            return;
        }
        listItem.setSelectedIndex(selectedIndex);
        body.layoutContainer();
        body.revalidate();
        listItem.requestFocus();
    }

    /**
     *
     * @param keyCode
     * @return nếu lớp con bắt hoàn toàn action này thì trả về false
     * giá trị trả về cho biết lớp BaseForm có tiếp tục xử lý sự kiện hay ko.
     */
    protected boolean keyPressed(int keyCode) {
        return true;
    }

    protected void onShowCompleted() {
    }

    protected void releaseAll() {
        listItem = null;
        form = null;
        textSearch = null;
        cmdBack = null;
        messageIcon = null;
        cmdMainScreen = null;
        cmdSearch = null;
        cmdView = null;
        panelSearch = null;
        stopLoadThumb();
        if (parentEntity != null) {
            parentEntity.removeAllIconOfChild("" + ItemEntity.TYPE_ARTICLE);
        }

        Util.gc();
    }

    protected void showPreviousScreen() {
        try {
            previous.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void backScreen() {
        releaseAll();
        showPreviousScreen();
    }

    protected int getMenubarHeight() {
        return getMenubarHeight(form);
    }

    protected int getTitleBarHeight() {
        return getTitleBarHeight(form);
    }

    public static int getMenubarHeight(Form frm) {
        //TODO: Nam edit
//        int height = frm.getMenuStyle().getFont().getHeight() + 4;
        int height;
        if (frm.getSoftButton(0) != null && frm.getSoftButton(0).getParent() != null) {
            height = frm.getSoftButton(0).getParent().getPreferredH();
        } else {
            height = frm.getMenuStyle().getFont().getHeight() + 4;
        }
        return Math.min(height, 22); //22 is height font in menubar
    }

    public static int getTitleBarHeight(Form frm) {
        //TODO: Nam edit
//        int height = frm.getTitleArea().getPreferredH();
        int height = frm.getTitleComponent().getPreferredH()
                + frm.getTitleStyle().getPadding(Component.TOP)
                + frm.getTitleStyle().getPadding(Component.BOTTOM);
        return Math.min(height, 26); //22 is height of throbber
    }

    public class ListItem extends List {

        public ListItem(Vector items) {
            super(items);
            setSelectCommandText(Resource.CMD_SELECT);
            addFocusListener(new FocusListener() {

                public void focusGained(Component cmp) {
                    Component c = getRenderer().getListCellRendererComponent(ListItem.this, getSelectedItem(), getSelectedIndex(), true);
                    c.setFocusPainted(true);
                }

                public void focusLost(Component cmp) {
                    Component c = getRenderer().getListCellRendererComponent(ListItem.this, getSelectedItem(), getSelectedIndex(), true);
                    c.setFocusPainted(false);
                }
            });
        }
    }

    class TextSearch extends TextField {

        Image iconSearch = AudioStore.getResource().getImage("search_text");

        public void paint(Graphics g) {
            if (!Display.getInstance().isTouchScreenDevice()) {
                int marginLeft = iconSearch.getWidth() + 5;
                getUnselectedStyle().setPadding(LEFT, marginLeft);
                getSelectedStyle().setPadding(LEFT, marginLeft);
                int y = getY() + (getHeight() - iconSearch.getHeight()) / 2;
                g.drawImage(iconSearch, getX(), y);
            }
            super.paint(g);
        }

        public void keyReleased(int keyCode) {
            int game = Display.getInstance().getGameAction(keyCode);
            if (!Display.getInstance().isTouchScreenDevice() && game == Display.GAME_FIRE) {
                search();
            } else {
                super.keyReleased(keyCode);
            }
        }
    }
}
